package cn.magicman.demo;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * 手写简单线程池（核心组件：任务队列、工作线程、状态控制）
 * 功能：复用线程执行任务，避免频繁创建/销毁线程的开销
 */
public class SimpleRYOThreadPool {
    // 1. 任务队列：存储等待执行的任务（阻塞队列，支持阻塞式提交）
    private final BlockingQueue<Runnable> taskQueue;
    // 2. 工作线程数组：复用的线程集合（固定数量）
    private final Thread[] workers;
    // 3. 线程池运行状态（volatile保证可见性，避免指令重排序）
    private volatile boolean running = true;

    /**
     * 构造方法：初始化线程池
     * @param corePoolSize 核心线程数（固定线程数量）
     * @param queueCapacity 任务队列容量（无界队列时设为Integer.MAX_VALUE）
     */
    public SimpleRYOThreadPool(int corePoolSize, int queueCapacity) {
        this.taskQueue = new LinkedBlockingQueue<>(queueCapacity);
        this.workers = new Thread[corePoolSize];
        // 初始化工作线程并启动
        for (int i = 0; i < corePoolSize; i++) {
            workers[i] = new Thread(new Worker(), "Worker-" + i);
            workers[i].start();
        }
    }

    /**
     * 提交任务到线程池
     * @param task 待执行的任务（非null）
     * @throws IllegalStateException 当线程池已关闭时抛出
     */
    public void submit(Runnable task) {
        if (!running) {
            throw new IllegalStateException("线程池已关闭，无法提交任务");
        }
        try {
            // 将任务放入队列（如果队列满，会阻塞当前线程）
            taskQueue.put(task);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt(); // 保留中断状态
            throw new RuntimeException("提交任务被中断", e);
        }
    }

    /**
     * 关闭线程池（优雅 shutdown）
     * 逻辑：停止接受新任务 → 中断所有工作线程（未执行的任务会继续） → 等待所有任务完成
     */
    public void shutdown() {
        running = false; // 标记线程池为关闭状态，停止接受新任务
        // 中断所有工作线程（触发Worker中的InterruptedException）
        for (Thread worker : workers) {
            worker.interrupt();
        }
        // 等待所有工作线程结束（保证剩余任务执行完毕）
        for (Thread worker : workers) {
            try {
                worker.join();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                throw new RuntimeException("等待线程结束被中断", e);
            }
        }
        System.out.println("【线程池状态】已完全关闭（剩余任务执行完毕）");
    }

    /**
     * 工作线程类（实现Runnable）
     * 功能：循环从任务队列取任务执行，直到线程池关闭且队列为空
     */
    private class Worker implements Runnable {
        @Override
        public void run() {
            // 循环条件：线程池运行中 或者 任务队列不为空（保证剩余任务执行完毕）
            while (running || !taskQueue.isEmpty()) {
                try {
                    // 从队列头部取任务（阻塞式：如果队列空，会等待直到有任务）
                    Runnable task = taskQueue.take();
                    // 执行任务（捕获任务中的异常，避免工作线程崩溃）
                    task.run();
                } catch (InterruptedException e) {
                    // 捕获中断异常（线程池关闭时触发），退出循环
                    System.out.println(Thread.currentThread().getName() + " 被中断（线程池关闭）");
                    break;
                } catch (Exception e) {
                    // 捕获任务执行中的异常，避免工作线程崩溃
                    System.out.println("【任务执行失败】" + e.getMessage());
                }
            }
            System.out.println(Thread.currentThread().getName() + " 退出运行");
        }
    }

    // ---------------------- 测试用例 ----------------------
    public static void main(String[] args) {
        // 1. 创建线程池：核心线程数3，任务队列容量10（无界队列可设为Integer.MAX_VALUE）
        SimpleRYOThreadPool threadPool = new SimpleRYOThreadPool(3, 10);

        // 2. 提交10个任务（模拟并发任务）
        for (int i = 0; i < 10; i++) {
            int taskId = i;
            threadPool.submit(() -> {
                System.out.println(Thread.currentThread().getName() + " 执行任务：" + taskId);
                // 模拟任务执行耗时（100ms）
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    System.out.println("任务" + taskId + " 被中断");
                }
            });
        }

        // 3. 关闭线程池（优雅等待所有任务完成）
        threadPool.shutdown();

        // 4. 主线程结束（线程池关闭后退出）
        System.out.println("【主线程】所有任务提交完毕，等待线程池关闭...");
    }
}